home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / comm / tcp / amitcptelnetf.lha / amitcp_telnet+ftp / ftp / ftp.c < prev    next >
C/C++ Source or Header  |  1993-08-13  |  39KB  |  1,964 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)ftp.c    5.28 (Berkeley) 4/20/89";
  20. #endif /* not lint */
  21.  
  22. #include <sys/param.h>
  23. #include <sys/stat.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/socket.h>
  26. #ifdef AMI_TCP
  27. #include <bsdsocket.h>
  28. #include <dos/dos.h>
  29. #else
  30. #include <ss/socket.h>
  31. #endif
  32. #include <sys/time.h>
  33. #ifndef AMI_TCP
  34. #include <sys/file.h>
  35. #endif
  36.  
  37. #include <netinet/in.h>
  38. #include <arpa/ftp.h>
  39. #include <arpa/telnet.h>
  40.  
  41. #include <stdio.h>
  42. #include <signal.h>
  43. #include <errno.h>
  44. #include <netdb.h>
  45. #include <fcntl.h>
  46. #ifndef AMI_TCP
  47. #include <pwd.h>
  48. #endif
  49. //#include <syslog.h>
  50.  
  51. #ifdef __STDC__
  52. #include <stdarg.h>
  53. #else
  54. #include <varargs.h>
  55. #endif
  56.  
  57. #ifdef __SASC
  58. #include <ios1.h>
  59. #endif
  60.  
  61. #include "ftp_var.h"
  62.  
  63. extern int Enable_Abort;
  64.  
  65. #ifndef MAXHOSTNAMELEN
  66. #define MAXHOSTNAMELEN 64
  67. #endif
  68.  
  69. #ifdef NOVFPRINTF
  70. #define vfprintf(a,b,c) _doprnt(b,c,a)
  71. #endif
  72.  
  73. #ifdef sun
  74. /* FD_SET wasn't defined until 4.0. its a cheap test for uid_t  presence */
  75. #ifndef FD_SET
  76. #define    NBBY    8        /* number of bits in a byte */
  77. /*
  78.  * Select uses bit masks of file descriptors in longs.
  79.  * These macros manipulate such bit fields (the filesystem macros use chars).
  80.  * FD_SETSIZE may be defined by the user, but the default here
  81.  * should be >= NOFILE (param.h).
  82.  */
  83. #ifndef    FD_SETSIZE
  84. #define    FD_SETSIZE    256
  85. #endif
  86.  
  87. typedef long    fd_mask;
  88. #define NFDBITS    (sizeof(fd_mask) * NBBY)    /* bits per mask */
  89. #ifndef howmany
  90. #define    howmany(x, y)    (((x)+((y)-1))/(y))
  91. #endif
  92.  
  93. #define    FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  94. #define    FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  95. #define    FD_ISSET(n, p)    ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  96. #define FD_ZERO(p)    bzero((char *)(p), sizeof(*(p)))
  97.  
  98. typedef int uid_t;
  99. typedef int gid_t;
  100. #endif /* FD_SET */
  101. #endif /*sun */
  102.  
  103. struct    sockaddr_in hisctladdr;
  104. struct    sockaddr_in data_addr;
  105. int    data = -1;
  106. int    abrtflag = 0;
  107. int    ptflag = 0;
  108. int    allbinary;
  109. struct    sockaddr_in myctladdr;
  110. sig_t    lostpeer();
  111. off_t    restart_point = 0;
  112. extern char *home;
  113. extern FILE *log_file;
  114.  
  115. int    cin, cout; /* these are FD's now, not FILE *'s */
  116. int    dataconn();
  117.  
  118. char *
  119. hookup(host, port)
  120.     char *host;
  121.     int port;
  122. {
  123.     register struct hostent *hp = 0;
  124.     int s,len;
  125.     static char hostnamebuf[80];
  126.  
  127.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  128.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  129.     if (hisctladdr.sin_addr.s_addr != -1) {
  130.         hisctladdr.sin_family = AF_INET;
  131.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  132.     } else {
  133.         hp = gethostbyname(host);
  134.         if (hp == NULL) {
  135.             fprintf(stderr, "ftp: %s: ", host);
  136.             herror((char *)NULL);
  137.             code = -1;
  138.             return((char *) 0);
  139.         }
  140.         hisctladdr.sin_family = hp->h_addrtype;
  141.         bcopy(hp->h_addr_list[0],
  142.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  143.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  144.     }
  145.     hostname = hostnamebuf;
  146.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  147.     if (s < 0) {
  148.         perror("ftp: socket");
  149.         code = -1;
  150.         return (0);
  151.     }
  152.     hisctladdr.sin_port = port;
  153.     while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
  154.         if (hp && hp->h_addr_list[1]) {
  155.             int oerrno = errno;
  156.  
  157.             fprintf(stderr, "ftp: connect to address %s: ",
  158.                 inet_ntoa(hisctladdr.sin_addr));
  159.             errno = oerrno;
  160.             perror((char *) 0);
  161.             hp->h_addr_list++;
  162.             bcopy(hp->h_addr_list[0],
  163.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  164.             fprintf(stdout, "Trying %s...\n",
  165.                 inet_ntoa(hisctladdr.sin_addr));
  166.             (void) close(s);
  167.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  168.             if (s < 0) {
  169.                 perror("ftp: socket");
  170.                 code = -1;
  171.                 return (0);
  172.             }
  173.             continue;
  174.         }
  175.         perror("ftp: connect");
  176.         code = -1;
  177.         goto bad;
  178.     }
  179.     len = sizeof (myctladdr);
  180.     if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
  181.         perror("ftp: getsockname");
  182.         code = -1;
  183.         goto bad;
  184.     }
  185.     cin = cout = s;
  186.     if (verbose)
  187.         printf("Connected to %s.\n", hostname);
  188.     if (getreply(0) > 2) {     /* read startup message from server */
  189.         code = -1;
  190.         goto bad;
  191.     }
  192. #ifdef SO_OOBINLINE
  193.     {
  194.     int on = 1;
  195.  
  196.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
  197.         < 0 && debug) {
  198.             perror("ftp: setsockopt");
  199.         }
  200.     }
  201. #endif /* SO_OOBINLINE */
  202.  
  203.     return (hostname);
  204. bad:
  205.     (void) s_close(s);
  206.     return ((char *)0);
  207. }
  208.  
  209. login(host)
  210.     char *host;
  211. {
  212.     char tmp[80];
  213.     char *user, *pass, *acct, *getlogin(), *getpass();
  214.     int n, aflag = 0;
  215.     char *myname;
  216.     extern char *mygetenv();
  217.  
  218.     myname = mygetenv("USERNAME");
  219.  
  220.     user = pass = acct = 0;
  221. #if 0
  222.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  223.         code = -1;
  224.         return(0);
  225.     }
  226. #endif
  227.     while (user == NULL) {
  228.                 if (myname)
  229.                         printf("Name (%s:%s): ", host, myname);
  230.                 else
  231.                         printf("Name (%s): ", host);
  232.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  233.         tmp[strlen(tmp) - 1] = '\0';
  234.         if (*tmp == '\0')
  235.             user = myname;
  236.         else
  237.             user = tmp;
  238.     }
  239. #ifdef FTP_LOG_USAGE
  240.     syslog(LOG_INFO, "FTP LOGIN by %s to %s as %s",
  241.            myname ? myname : "unknown", host, user);
  242. #endif /* FTP_LOG_USAGE */
  243.     n = command("USER %s", user);
  244.     if (n == CONTINUE) {
  245.         if (pass == NULL)
  246.             pass = getpass("Password:");
  247.         n = command("PASS %s", pass);
  248.     }
  249.     if (n == CONTINUE) {
  250.         aflag++;
  251.         acct = getpass("Account:");
  252.         n = command("ACCT %s", acct);
  253.     }
  254.     if (n != COMPLETE) {
  255.         fprintf(stderr, "Login failed.\n");
  256.         return (0);
  257.     }
  258.     if (!aflag && acct != NULL)
  259.         (void) command("ACCT %s", acct);
  260.     if (proxy)
  261.         return(1);
  262.     for (n = 0; n < macnum; ++n) {
  263.         if (!strcmp("init", macros[n].mac_name)) {
  264.             (void) strcpy(line, "$init");
  265.             makeargv();
  266.             domacro(margc, margv);
  267.             break;
  268.         }
  269.     }
  270.     return (1);
  271. }
  272.  
  273. #if 0
  274. sig_t
  275. cmdabort()
  276. {
  277.     extern jmp_buf ptabort;
  278.  
  279.     printf("\n");
  280.     (void) fflush(stdout);
  281.     abrtflag++;
  282.     if (ptflag)
  283.         longjmp(ptabort,1);
  284. }
  285. #endif
  286.  
  287. /*VARARGS1*/
  288. #ifdef __STDC__
  289. int command(char * fmt, ...)
  290. #else     
  291. command(va_alist)
  292.      va_dcl
  293. #endif       
  294. {
  295.     va_list ap;
  296. #ifndef __STDC__    
  297.     char *fmt;
  298. #endif    
  299.     int r;
  300. //    sig_t (*oldintr)(), cmdabort();
  301.     int len; char str_buf[256];
  302.  
  303.     abrtflag = 0;
  304.     if (debug) {
  305.         printf("---> ");
  306. #ifdef __STDC__
  307.         va_start(ap, fmt);
  308. #else        
  309.         va_start(ap);
  310.         fmt = va_arg(ap, char *);
  311. #endif        
  312.         vfprintf(stdout, fmt, ap);
  313.         va_end(ap);
  314.         printf("\n");
  315.         (void) fflush(stdout);
  316.     }
  317.     if (cout == -1) {
  318.         perror ("No control connection for command");
  319.         code = -1;
  320.         return (0);
  321.     }
  322. //    oldintr = signal(SIGINT,cmdabort);
  323. #ifdef __STDC__
  324.     va_start(ap, fmt);
  325. #else    
  326.     va_start(ap);
  327.     fmt = va_arg(ap, char *);
  328. #endif    
  329.     len = vsprintf(str_buf, fmt, ap);
  330.     strcpy(&str_buf[len],"\r\n");
  331.     send(cout, str_buf, len+2, 0);
  332.     va_end(ap);
  333.     cpend = 1;
  334.     r = getreply(!strcmp(fmt, "QUIT"));
  335. //    if (abrtflag && oldintr != SIG_IGN)
  336. //        (*oldintr)();
  337. //    (void) signal(SIGINT, oldintr);
  338.     return(r);
  339. }
  340.  
  341. char reply_string[BUFSIZ];        /* last line of previous reply */
  342.  
  343. #include <ctype.h>
  344.  
  345. getreply(expecteof)
  346.     int expecteof;
  347. {
  348.     register int n, c;
  349.     register int dig;
  350.     register char *cp;
  351.     int originalcode = 0, continuation = 0;
  352. //    sig_t (*oldintr)(), cmdabort();
  353.     int pflag = 0;
  354.     char *pt = pasv;
  355.     char str_buf[8];
  356.  
  357. //    oldintr = signal(SIGINT,cmdabort);
  358.     for (;;) {
  359.         dig = n = code = 0;
  360.         cp = reply_string;
  361.         while ((c = sgetc(cin)) != '\n') {
  362.             if (c == IAC) {     /* handle telnet commands */
  363.                 switch (sgetc(cin)) {
  364.                 case WILL:
  365.                 case WONT:
  366.                     str_buf[0] = IAC; str_buf[1] = DONT;
  367.                     str_buf[2] = sgetc(cin);
  368.                     send(cout, str_buf, 3, 0);
  369.                     break;
  370.                 case DO:
  371.                 case DONT:
  372.                     str_buf[0] = IAC; str_buf[1] = DONT;
  373.                     str_buf[2] = sgetc(cin);
  374.                     send(cout, str_buf, 3, 0);
  375.                     break;
  376.                 default:
  377.                     break;
  378.                 }
  379.                 continue;
  380.             }
  381.             dig++;
  382.             if (c == EOF) {
  383.                 if (expecteof) {
  384. //                    (void) signal(SIGINT,oldintr);
  385.                     code = 221;
  386.                     return (0);
  387.                 }
  388.                 lostpeer();
  389.                 if (verbose) {
  390.                     printf("421 Service not available, remote server has closed connection\n");
  391.                     (void) fflush(stdout);
  392.                 }
  393.                 code = 421;
  394.                 return(4);
  395.             }
  396.             if (c != '\r' && (verbose > 0 ||
  397.                 (verbose > -1 && n == '5' && dig > 4))) {
  398.                 if (proxflag &&
  399.                    (dig == 1 || dig == 5 && verbose == 0))
  400.                     printf("%s:",hostname);
  401.                 (void) putchar(c);
  402.             }
  403.             if (dig < 4 && isdigit(c))
  404.                 code = code * 10 + (c - '0');
  405.             if (!pflag && code == 227)
  406.                 pflag = 1;
  407.             if (dig > 4 && pflag == 1 && isdigit(c))
  408.                 pflag = 2;
  409.             if (pflag == 2) {
  410.                 if (c != '\r' && c != ')')
  411.                     *pt++ = c;
  412.                 else {
  413.                     *pt = '\0';
  414.                     pflag = 3;
  415.                 }
  416.             }
  417.             if (dig == 4 && c == '-') {
  418.                 if (continuation)
  419.                     code = 0;
  420.                 continuation++;
  421.             }
  422.             if (n == 0)
  423.                 n = c;
  424.             if (cp < &reply_string[sizeof(reply_string) - 1])
  425.                 *cp++ = c;
  426.         }
  427.         if (verbose > 0 || verbose > -1 && n == '5') {
  428.             (void) putchar(c);
  429.             (void) fflush (stdout);
  430.         }
  431.         if (continuation && code != originalcode) {
  432.             if (originalcode == 0)
  433.                 originalcode = code;
  434.             continue;
  435.         }
  436.         *cp = '\0';
  437.         if (n != '1')
  438.             cpend = 0;
  439. //        (void) signal(SIGINT,oldintr);
  440.         if (code == 421 || originalcode == 421)
  441.             lostpeer();
  442. //        if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  443. //            (*oldintr)();
  444.         return (n - '0');
  445.     }
  446. }
  447.  
  448. empty(mask, sec)
  449.     struct fd_set *mask;
  450.     int sec;
  451. {
  452.     struct timeval t;
  453.  
  454.     t.tv_sec = (long) sec;
  455.     t.tv_usec = 0;
  456.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  457. }
  458.  
  459. jmp_buf    sendabort;
  460.  
  461. abortsend()
  462. {
  463.  
  464.     mflag = 0;
  465.     abrtflag = 0;
  466.     printf("\nsend aborted\n");
  467.     (void) fflush(stdout);
  468.     longjmp(sendabort, 1);
  469. }
  470.  
  471. char *basename(char *fname)
  472. {
  473. static const char delim[] = ":/]\\";
  474.  
  475.     const char *p;
  476.     char *fn;
  477.  
  478.     for (fn = &fname[strlen(fname)]; --fn >= fname;)
  479.     {    for (p = delim; *p; p++)
  480.         {    if (*fn == *p) break;
  481.             if (*fn == ';') *fn = 0;    /* strip VMS version no. */
  482.         }
  483.         if (*p) break;
  484.     }
  485.     if (fn >= fname) return fn+1;
  486.     return fname;
  487. }
  488.  
  489. #define HASHBYTES 1024
  490. char buf[BUFSIZ];
  491.  
  492. sendrequest(cmd, local, remote, printnames)
  493.     char *cmd, *local, *remote;
  494.     int printnames;
  495. {
  496.     FILE *fin;
  497.     int dout;
  498.     int (*closefunc)(), fclose();
  499. //    sig_t (*oldintr)(), (*oldintp)();
  500.     int abortsend();
  501.     char *bufp;
  502.     long bytes = 0, hashbytes = HASHBYTES;
  503.     register int c, d;
  504.     struct stat st;
  505.     struct timeval start, stop;
  506.     char *mode;
  507.     char real_local[128];
  508.  
  509.     if (local[0] != '-')
  510.     {    joinpath(real_local,uldir,basename(local));
  511.         local = real_local;
  512.     }
  513.  
  514.     if (verbose && printnames) {
  515.         if (local && *local != '-')
  516.             printf("local: %s ", local);
  517.         if (remote)
  518.             printf("remote: %s\n", remote);
  519.     }
  520.     if (proxy) {
  521.         proxtrans(cmd, local, remote);
  522.         return;
  523.     }
  524.     closefunc = NULL;
  525. //    oldintr = NULL;
  526. //    oldintp = NULL;
  527.     mode = "w";
  528.     if (setjmp(sendabort)) {
  529.         while (cpend) {
  530.             (void) getreply(0);
  531.         }
  532.         if (data >= 0) {
  533.             (void) s_close(data);
  534.             data = -1;
  535.         }
  536. //        if (oldintr)
  537. //            (void) signal(SIGINT,oldintr);
  538. //        if (oldintp)
  539. //            (void) signal(SIGPIPE,oldintp);
  540.         code = -1;
  541.         return;
  542.     }
  543. //    oldintr = signal(SIGINT, abortsend);
  544.     if (strcmp(local, "-") == 0)
  545.         fin = stdin;
  546. #if 0
  547.     else if (*local == '|') {
  548.         oldintp = signal(SIGPIPE,SIG_IGN);
  549.         fin = popen(local + 1, "r");
  550.         if (fin == NULL) {
  551.             perror(local + 1);
  552.             (void) signal(SIGINT, oldintr);
  553.             (void) signal(SIGPIPE, oldintp);
  554.             code = -1;
  555.             return;
  556.         }
  557.         closefunc = pclose;
  558.     }
  559. #endif
  560.     else
  561.     {
  562.         fin = fopen(local, "r");
  563.         if (fin == NULL) {
  564.             perror(local);
  565. //            (void) signal(SIGINT, oldintr);
  566.             code = -1;
  567.             return;
  568.         }
  569.         closefunc = fclose;
  570. #if 0
  571.         if (fstat(fileno(fin), &st) < 0 ||
  572.             (st.st_mode&S_IFMT) != S_IFREG) {
  573.             fprintf(stdout, "%s: not a plain file.\n", local);
  574.             (void) signal(SIGINT, oldintr);
  575.             fclose(fin);
  576.             code = -1;
  577.             return;
  578.         }
  579. #endif
  580.     }
  581.     if (initconn()) {
  582. //        (void) signal(SIGINT, oldintr);
  583. //        if (oldintp)
  584. //            (void) signal(SIGPIPE, oldintp);
  585.         code = -1;
  586.         if (closefunc != NULL)
  587.             (*closefunc)(fin);
  588.         return;
  589.     }
  590.     if (setjmp(sendabort))
  591.         goto abort;
  592.  
  593. #ifdef __SASC
  594.     SetMode(chkufb(fileno(stdin))->ufbfh,1L);
  595. #else
  596.     SetMode(_devtab[fileno(stdin)].fd,1L);
  597. #endif
  598.     Enable_Abort = 0;
  599.  
  600.     if (restart_point &&
  601.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  602.         if (fseek(fin, (long) restart_point, 0) < 0) {
  603.             perror(local);
  604.             restart_point = 0;
  605.             if (closefunc != NULL)
  606.                 (*closefunc)(fin);
  607. #ifdef __SASC
  608.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  609. #else
  610.             SetMode(_devtab[fileno(stdin)].fd,0L);
  611. #endif
  612.             Enable_Abort = 1;
  613.             return;
  614.         }
  615.         if (command("REST %ld", (long) restart_point)
  616.             != CONTINUE) {
  617.             restart_point = 0;
  618.             if (closefunc != NULL)
  619.                 (*closefunc)(fin);
  620. #ifdef __SASC
  621.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  622. #else
  623.             SetMode(_devtab[fileno(stdin)].fd,0L);
  624. #endif
  625.             Enable_Abort = 1;
  626.             return;
  627.         }
  628.         restart_point = 0;
  629.         mode = "r+w";
  630.     }
  631.     if (remote) {
  632.         if (command("%s %s", cmd, remote) != PRELIM) {
  633. //            (void) signal(SIGINT, oldintr);
  634. //            if (oldintp)
  635. //                (void) signal(SIGPIPE, oldintp);
  636.             if (closefunc != NULL)
  637.                 (*closefunc)(fin);
  638. #ifdef __SASC
  639.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  640. #else
  641.             SetMode(_devtab[fileno(stdin)].fd,0L);
  642. #endif
  643.             Enable_Abort = 1;
  644.             return;
  645.         }
  646.     } else
  647.         if (command("%s", cmd) != PRELIM) {
  648. //            (void) signal(SIGINT, oldintr);
  649. //            if (oldintp)
  650. //                (void) signal(SIGPIPE, oldintp);
  651.             if (closefunc != NULL)
  652.                 (*closefunc)(fin);
  653. #ifdef __SASC
  654.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  655. #else
  656.             SetMode(_devtab[fileno(stdin)].fd,0L);
  657. #endif
  658.             Enable_Abort = 1;
  659.             return;
  660.         }
  661.     dout = dataconn(mode);
  662.     if (dout == -1)
  663.         goto abort;
  664.     (void) mygettimeofday(&start, (struct timezone *)0);
  665. //    oldintp = signal(SIGPIPE, SIG_IGN);
  666.     switch (type) {
  667.  
  668.     case TYPE_I:
  669.     case TYPE_L:
  670.     case TYPE_A:
  671.         errno = d = 0;
  672.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  673.             bytes += c;
  674.             for (bufp = buf; c > 0; c -= d, bufp += d)
  675.                 if ((d = send(dout, bufp, c, 0)) <= 0)
  676.                     break;
  677.             if (hash) {
  678.                 while (bytes >= hashbytes) {
  679.                     (void) putchar('#');
  680.                     hashbytes += HASHBYTES;
  681.                 }
  682.                 (void) fflush(stdout);
  683.             }
  684. #ifdef __SASC
  685.             if (WaitForChar(chkufb(fileno(stdin))->ufbfh, 0L) == DOSTRUE)
  686. #else
  687.             if (WaitForChar(_devtab[fileno(stdin)].fd, 0L) == DOSTRUE)
  688. #endif
  689.                 goto abort;
  690.             if (SetSignal (0L,SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) goto abort;
  691.         }
  692.         if (hash && bytes > 0) {
  693.             if (bytes < HASHBYTES)
  694.                 (void) putchar('#');
  695.             (void) putchar('\n');
  696.             (void) fflush(stdout);
  697.         }
  698.         if (c < 0)
  699.             perror(local);
  700.         if (d <= 0) {
  701.             if (d == 0)
  702.                 fprintf(stderr, "netout: write returned 0?\n");
  703.             else if (errno != EPIPE) 
  704.                 perror("netout");
  705.             bytes = -1;
  706.         }
  707.         break;
  708.  
  709. #if 0
  710.     case TYPE_A:
  711.         while ((c = getc(fin)) != EOF) {
  712.             if (c == '\n') {
  713.                 while (hash && (bytes >= hashbytes)) {
  714.                     (void) putchar('#');
  715.                     (void) fflush(stdout);
  716.                     hashbytes += HASHBYTES;
  717.                 }
  718.                 if (ferror(dout))
  719.                     break;
  720.                 send(dout, "\r", 1, 0);
  721.                 bytes++;
  722.             }
  723.             send(dout, &c, 1, 0);
  724.             bytes++;
  725.     /*        if (c == '\r') {                  */
  726.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  727.     /*            bytes++;                */
  728.     /*        }                                      */    
  729.         }
  730.         if (hash) {
  731.             if (bytes < hashbytes)
  732.                 (void) putchar('#');
  733.             (void) putchar('\n');
  734.             (void) fflush(stdout);
  735.         }
  736.         if (ferror(fin))
  737.             perror(local);
  738.         if (ferror(dout)) {
  739.             if (errno != EPIPE)
  740.                 perror("netout");
  741.             bytes = -1;
  742.         }
  743.         break;
  744. #endif
  745.     }
  746.     (void) mygettimeofday(&stop, (struct timezone *)0);
  747.     if (closefunc != NULL)
  748.         (*closefunc)(fin);
  749.     s_close(dout);
  750.     (void) getreply(0);
  751. //    (void) signal(SIGINT, oldintr);
  752. //    if (oldintp)
  753. //        (void) signal(SIGPIPE, oldintp);
  754.     if (bytes > 0)
  755. #ifdef FTP_LOG_USAGE
  756.         ptransfer("sent", bytes, &start, &stop, local);
  757. #else
  758.     {   ptransfer("sent", bytes, &start, &stop);
  759.         if (log_file) fprintf(log_file,"%s %d\n",hostname, bytes);
  760.     }
  761. #endif /* FTP_LOG_USAGE */
  762. #ifdef __SASC
  763.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  764. #else
  765.     SetMode(_devtab[fileno(stdin)].fd,0L);
  766. #endif
  767.     Enable_Abort = 1;
  768.     return;
  769. abort:
  770.     (void) mygettimeofday(&stop, (struct timezone *)0);
  771. //    (void) signal(SIGINT, oldintr);
  772. //    if (oldintp)
  773. //        (void) signal(SIGPIPE, oldintp);
  774.     if (!cpend) {
  775.         code = -1;
  776.         return;
  777.     }
  778.     if (data >= 0) {
  779.         (void) s_close(data);
  780.         data = -1;
  781.     }
  782.     dout = -1;
  783.     (void) getreply(0);
  784.     code = -1;
  785.     if (closefunc != NULL && fin != NULL)
  786.         (*closefunc)(fin);
  787.     if (bytes > 0)
  788. #ifdef FTP_LOG_USAGE
  789.         ptransfer("sent", bytes, &start, &stop, local);
  790. #else
  791.     {   ptransfer("sent", bytes, &start, &stop);
  792.         if (log_file) fprintf(log_file,"%s %d\n",hostname, bytes);
  793.     }
  794. #endif /* FTP_LOG_USAGE */
  795. #ifdef __SASC
  796.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  797. #else
  798.     SetMode(_devtab[fileno(stdin)].fd,0L);
  799. #endif
  800.     Enable_Abort = 1;
  801. }
  802.  
  803. display_temp(FILE *fp)
  804. {    char command[128];
  805.     char fname[128];
  806.     char *pager;
  807.  
  808.     fclose(fp); /* This looks stupid, but it's correct */
  809.     if ((pager = mygetenv("PAGER")) == 0)
  810.         pager = "more";
  811.     joinpath(fname, dldir, ".temp");
  812.     sprintf(command,"%s %s", pager, fname);
  813. #ifdef __SASC
  814.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  815. #else
  816.     SetMode(_devtab[fileno(stdin)].fd,0L);
  817. #endif
  818.     System(command,0L);
  819. #ifdef __SASC
  820.     SetMode(chkufb(fileno(stdin))->ufbfh,1L);
  821. #else
  822.     SetMode(_devtab[fileno(stdin)].fd,1L);
  823. #endif
  824.  
  825. }
  826.  
  827. jmp_buf    recvabort;
  828.  
  829. abortrecv()
  830. {
  831.  
  832.     mflag = 0;
  833.     abrtflag = 0;
  834.     printf("\n");
  835.     (void) fflush(stdout);
  836.     longjmp(recvabort, 1);
  837. }
  838.  
  839. recvrequest(cmd, local, remote, mode, printnames)
  840.     char *cmd, *local, *remote, *mode;
  841. {
  842.     FILE *fout;
  843.     int din;
  844.     int (*closefunc)(), fclose();
  845. //    sig_t (*oldintr)(), (*oldintp)();
  846.     int abortrecv();
  847.     int oldverbose, oldtype = 0, is_retr, tcrflag, nfnd, bare_lfs = 0;
  848.     char *gunique(), msg;
  849.     static char *buf;
  850.     static int bufsize;
  851.     long bytes = 0, hashbytes = HASHBYTES;
  852.     struct fd_set mask;
  853.     register int c, d;
  854.     struct timeval start, stop;
  855.     struct stat st;
  856.     char str_buf[16];
  857.     extern char *malloc();
  858.     char real_local[128];
  859.  
  860.     if (local[0] != '-')
  861.     {    joinpath (real_local, dldir, basename(local));
  862.         local = real_local;
  863.     }
  864.  
  865.     is_retr = strcmp(cmd, "RETR") == 0;
  866.     if (is_retr && verbose && printnames) {
  867.         if (local && *local != '-')
  868.             printf("local: %s ", local);
  869.         if (remote)
  870.             printf("remote: %s\n", remote);
  871.     }
  872.     if (proxy && is_retr) {
  873.         proxtrans(cmd, local, remote);
  874.         return;
  875.     }
  876.     closefunc = NULL;
  877. //    oldintr = NULL;
  878. //    oldintp = NULL;
  879.     tcrflag = !crflag && is_retr;
  880.     if (setjmp(recvabort)) {
  881.         while (cpend) {
  882.             (void) getreply(0);
  883.         }
  884.         if (data >= 0) {
  885.             (void) s_close(data);
  886.             data = -1;
  887.         }
  888. //        if (oldintr)
  889. //            (void) signal(SIGINT, oldintr);
  890.         code = -1;
  891.         return;
  892.     }
  893. //    oldintr = signal(SIGINT, abortrecv);
  894.     if (strcmp(local, "-") && *local != '|') {
  895.         if (access(local, 2) < 0) {
  896.             char *dir = rindex(local, '/');
  897.  
  898. #ifdef AZTEC_C
  899.             /* Aztec's errors are different from those in net includes */
  900.             if (errno != 1 /*ENOENT*/ && errno != 10 /*EACCES*/)
  901. #else
  902.             if (errno != ENOENT && errno != EACCES)
  903. #endif
  904.             {    perror(local);
  905. //                (void) signal(SIGINT, oldintr);
  906.                 code = -1;
  907.                 return;
  908.             }
  909.             if (dir != NULL)
  910.                 *dir = 0;
  911.             if (dir != NULL)
  912.                 *dir = '/';
  913.             if (!runique && errno == EACCES) {
  914.                 perror(local);
  915. //                (void) signal(SIGINT, oldintr);
  916.                 code = -1;
  917.                 return;
  918.             }
  919.         }
  920.         else if (runique && (local = gunique(local)) == NULL) {
  921. //            (void) signal(SIGINT, oldintr);
  922.             code = -1;
  923.             return;
  924.         }
  925.     }
  926.     if (initconn()) {
  927. //        (void) signal(SIGINT, oldintr);
  928.         code = -1;
  929.         return;
  930.     }
  931.     if (setjmp(recvabort))
  932.         goto abort;
  933.  
  934. #ifdef __SASC
  935.     SetMode(chkufb(fileno(stdin))->ufbfh,1L);
  936. #else
  937.     SetMode(_devtab[fileno(stdin)].fd,1L);
  938. #endif
  939.     Enable_Abort = 0;
  940.  
  941.     if (!is_retr) {
  942.         if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) {
  943.             oldtype = type;
  944.             oldverbose = verbose;
  945.             if (!debug)
  946.                 verbose = 0;
  947.             setascii();
  948.             verbose = oldverbose;
  949.         }
  950.     } else if (restart_point) {
  951.         if (command("REST %ld", (long) restart_point) != CONTINUE)
  952.             {
  953. #ifdef __SASC
  954.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  955. #else
  956.             SetMode(_devtab[fileno(stdin)].fd,0L);
  957. #endif
  958.             Enable_Abort = 1;
  959.             return;
  960.             }
  961.     }
  962.     if (remote) {
  963.         if (command("%s %s", cmd, remote) != PRELIM) {
  964. //            (void) signal(SIGINT, oldintr);
  965.             if (oldtype) {
  966.                 if (!debug)
  967.                     verbose = 0;
  968.                 switch (oldtype) {
  969.                     case TYPE_I:
  970.                         setbinary();
  971.                         break;
  972.                     case TYPE_E:
  973.                         setebcdic();
  974.                         break;
  975.                     case TYPE_L:
  976.                         settenex();
  977.                         break;
  978.                 }
  979.                 verbose = oldverbose;
  980.             }
  981. #ifdef __SASC
  982.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  983. #else
  984.             SetMode(_devtab[fileno(stdin)].fd,0L);
  985. #endif
  986.             Enable_Abort = 1;
  987.             return;
  988.         }
  989.     } else {
  990.         if (command("%s", cmd) != PRELIM) {
  991. //            (void) signal(SIGINT, oldintr);
  992.             if (oldtype) {
  993.                 if (!debug)
  994.                     verbose = 0;
  995.                 switch (oldtype) {
  996.                     case TYPE_I:
  997.                         setbinary();
  998.                         break;
  999.                     case TYPE_E:
  1000.                         setebcdic();
  1001.                         break;
  1002.                     case TYPE_L:
  1003.                         settenex();
  1004.                         break;
  1005.                 }
  1006.                 verbose = oldverbose;
  1007.             }
  1008. #ifdef __SASC
  1009.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1010. #else
  1011.             SetMode(_devtab[fileno(stdin)].fd,0L);
  1012. #endif
  1013.             Enable_Abort = 1;
  1014.             return;
  1015.         }
  1016.     }
  1017.     din = dataconn("r");
  1018.     if (din == -1)
  1019.         goto abort;
  1020.     if (strcmp(local, "-") == 0)
  1021.     {    joinpath(real_local, dldir, ".temp");
  1022.         fout = fopen(real_local,"w");
  1023.         if (fout == NULL) {
  1024.             perror(local);
  1025.             goto abort;
  1026.         }
  1027.         closefunc = display_temp;
  1028.     }
  1029. #if 0
  1030.     else if (*local == '|') {
  1031.         oldintp = signal(SIGPIPE, SIG_IGN);
  1032.         fout = popen(local + 1, "w");
  1033.         if (fout == NULL) {
  1034.             perror(local+1);
  1035.             goto abort;
  1036.         }
  1037.         closefunc = pclose;
  1038.     }
  1039. #endif
  1040.     else
  1041.     {    fout = fopen(local, mode);
  1042.         if (fout == NULL) {
  1043.             perror(local);
  1044.             goto abort;
  1045.         }
  1046.         closefunc = fclose;
  1047.     }
  1048. #if 0
  1049.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  1050.         st.st_blksize = BUFSIZ;
  1051.     if (st.st_blksize > bufsize) {
  1052.         if (buf)
  1053.             (void) free(buf);
  1054.         buf = malloc((unsigned)st.st_blksize);
  1055.         if (buf == NULL) {
  1056.             perror("malloc");
  1057.             bufsize = 0;
  1058.             goto abort;
  1059.         }
  1060.         bufsize = st.st_blksize;
  1061.     }
  1062. #else
  1063.     if (BUFSIZ > bufsize) {
  1064.         if (buf)
  1065.             free(buf);
  1066.         buf = malloc(BUFSIZ);
  1067.         if (buf == NULL) {
  1068.             perror("malloc");
  1069.             bufsize = 0;
  1070.             goto abort;
  1071.         }
  1072.         bufsize = BUFSIZ;
  1073.     }
  1074. #endif
  1075.     (void) mygettimeofday(&start, (struct timezone *)0);
  1076.     switch (type) {
  1077.  
  1078.     case TYPE_A:
  1079.     case TYPE_I:
  1080.     case TYPE_L:
  1081.         if (restart_point &&
  1082.             lseek(fileno(fout), (long) restart_point, 0) < 0) {
  1083.             perror(local);
  1084.             if (closefunc != NULL)
  1085.                 (*closefunc)(fout);
  1086. #ifdef __SASC
  1087.             SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1088. #else
  1089.             SetMode(_devtab[fileno(stdin)].fd,0L);
  1090. #endif
  1091.             Enable_Abort = 1;
  1092.             return;
  1093.         }
  1094.         errno = d = 0;
  1095.         while ((c = recv(din, buf, bufsize, 0)) > 0) {
  1096.             if ((d = write(fileno(fout), buf, c)) != c)
  1097.                 break;
  1098.             bytes += c;
  1099.             if (hash) {
  1100.                 while (bytes >= hashbytes) {
  1101.                     (void) putchar('#');
  1102.                     hashbytes += HASHBYTES;
  1103.                 }
  1104.                 (void) fflush(stdout);
  1105.             }
  1106. #ifdef __SASC
  1107.             if (WaitForChar(chkufb(fileno(stdin))->ufbfh, 0L) == DOSTRUE)
  1108. #else
  1109.             if (WaitForChar(_devtab[fileno(stdin)].fd, 0L) == DOSTRUE)
  1110. #endif
  1111.                 goto abort;
  1112.             if (SetSignal (0L,SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) goto abort;
  1113.         }
  1114.         if (hash && bytes > 0) {
  1115.             if (bytes < HASHBYTES)
  1116.                 (void) putchar('#');
  1117.             (void) putchar('\n');
  1118.             (void) fflush(stdout);
  1119.         }
  1120.         if (c < 0) {
  1121.             if (errno != EPIPE)
  1122.                 perror("netin");
  1123.             bytes = -1;
  1124.         }
  1125.         if (d < c) {
  1126.             if (d < 0)
  1127.                 perror(local);
  1128.             else
  1129.                 fprintf(stderr, "%s: short write\n", local);
  1130.         }
  1131.         break;
  1132.  
  1133. #if 0
  1134.     case TYPE_A:
  1135.         if (restart_point) {
  1136.             register int i, n, c;
  1137.  
  1138.             if (fseek(fout, 0L, L_SET) < 0)
  1139.                 goto done;
  1140.             n = restart_point;
  1141.             i = 0;
  1142.             while (i++ < n) {
  1143.                 if ((c=getc(fout)) == EOF)
  1144.                     goto done;
  1145.                 if (c == '\n')
  1146.                     i++;
  1147.             }
  1148.             if (fseek(fout, 0L, L_INCR) < 0) {
  1149. done:
  1150.                 perror(local);
  1151.                 if (closefunc != NULL)
  1152.                     (*closefunc)(fout);
  1153.                 return;
  1154.             }
  1155.         }
  1156.         while ((c = getc(din)) != EOF) {
  1157.             if (c == '\n')
  1158.                 bare_lfs++;
  1159.             while (c == '\r') {
  1160.                 while (hash && (bytes >= hashbytes)) {
  1161.                     (void) putchar('#');
  1162.                     (void) fflush(stdout);
  1163.                     hashbytes += HASHBYTES;
  1164.                 }
  1165.                 bytes++;
  1166.                 if ((c = getc(din)) != '\n' || tcrflag) {
  1167.                     if (ferror(fout))
  1168.                         goto break2;
  1169.                     (void) putc('\r', fout);
  1170.                     if (c == '\0') {
  1171.                         bytes++;
  1172.                         goto contin2;
  1173.                     }
  1174.                     if (c == EOF)
  1175.                         goto contin2;
  1176.                 }
  1177.             }
  1178.             (void) putc(c, fout);
  1179.             bytes++;
  1180.     contin2:    ;
  1181.         }
  1182. break2:
  1183.         if (bare_lfs) {
  1184.             printf("WARNING! %d bare linefeeds received in ASCII mode\n");
  1185.             printf("File may not have transferred correctly.\n");
  1186.         }
  1187.         if (hash) {
  1188.             if (bytes < hashbytes)
  1189.                 (void) putchar('#');
  1190.             (void) putchar('\n');
  1191.             (void) fflush(stdout);
  1192.         }
  1193.         if (ferror(din)) {
  1194.             if (errno != EPIPE)
  1195.                 perror("netin");
  1196.             bytes = -1;
  1197.         }
  1198.         if (ferror(fout))
  1199.             perror(local);
  1200.         break;
  1201. #endif
  1202.     }
  1203.  
  1204.     if (closefunc != NULL)
  1205.         (*closefunc)(fout);
  1206. //    (void) signal(SIGINT, oldintr);
  1207. //    if (oldintp)
  1208. //        (void) signal(SIGPIPE, oldintp);
  1209.     (void) mygettimeofday(&stop, (struct timezone *)0);
  1210.     (void) s_close (din);
  1211.     (void) getreply(0);
  1212.  
  1213. #ifdef __SASC
  1214.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1215. #else
  1216.     SetMode(_devtab[fileno(stdin)].fd,0L);
  1217. #endif
  1218.     Enable_Abort = 1;
  1219.  
  1220.     if (bytes > 0)
  1221. #ifdef FTP_LOG_USAGE
  1222.         ptransfer("received", bytes, &start, &stop, remote);
  1223. #else
  1224.     {   ptransfer("received", bytes, &start, &stop);
  1225.         if (log_file) fprintf(log_file,"%s %d\n",hostname, bytes);
  1226.     }
  1227. #endif /* FTP_LOG_USAGE */
  1228.     if (oldtype) {
  1229.         if (!debug)
  1230.             verbose = 0;
  1231.         switch (oldtype) {
  1232.             case TYPE_I:
  1233.                 setbinary();
  1234.                 break;
  1235.             case TYPE_E:
  1236.                 setebcdic();
  1237.                 break;
  1238.             case TYPE_L:
  1239.                 settenex();
  1240.                 break;
  1241.         }
  1242.         verbose = oldverbose;
  1243.     }
  1244.     return;
  1245. abort:
  1246. /* abort using RFC959 recommended IP,SYNC sequence  */
  1247.  
  1248.     (void) mygettimeofday(&stop, (struct timezone *)0);
  1249. //    if (oldintp)
  1250. //        (void) signal(SIGPIPE, oldintr);
  1251. //    (void) signal(SIGINT,SIG_IGN);
  1252.     if (oldtype) {
  1253.         if (!debug)
  1254.             verbose = 0;
  1255.         switch (oldtype) {
  1256.             case TYPE_I:
  1257.                 setbinary();
  1258.                 break;
  1259.             case TYPE_E:
  1260.                 setebcdic();
  1261.                 break;
  1262.             case TYPE_L:
  1263.                 settenex();
  1264.                 break;
  1265.         }
  1266.         verbose = oldverbose;
  1267.     }
  1268.     if (!cpend) {
  1269.         code = -1;
  1270. //        (void) signal(SIGINT,oldintr);
  1271.         return;
  1272.     }
  1273.  
  1274.     str_buf[0] = IAC; str_buf[1] = IP;
  1275.     send(cout, str_buf, 2, 0);
  1276.     str_buf[0] = IAC; str_buf[1] = DM;
  1277. /* send IAC in urgent mode instead of DM because UNIX places oob mark */
  1278. /* after urgent byte rather than before as now is protocol            */
  1279. #if 0
  1280.     if (send(cout,str_buf,2,MSG_OOB) != 2) {
  1281.         perror("abort");
  1282.     }
  1283. #endif
  1284.     sprintf(str_buf,"ABOR\r\n");
  1285.     send(cout, str_buf, 6, 0);
  1286.     FD_ZERO(&mask);
  1287.     FD_SET(cin, &mask);
  1288.     if (din) { 
  1289.         FD_SET(din, &mask);
  1290.     }
  1291.     if ((nfnd = empty(&mask,10)) <= 0) {
  1292.         if (nfnd < 0) {
  1293.             perror("abort");
  1294.         }
  1295.         code = -1;
  1296.         lostpeer();
  1297.     }
  1298.     if (din && FD_ISSET(din, &mask)) {
  1299.         while ((c = read(din, buf, bufsize)) > 0)
  1300.             ;
  1301.     }
  1302.     if (data >= 0) {
  1303.         (void) s_close(data);
  1304.         data = -1;
  1305.     }
  1306.     if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
  1307.         (void) getreply(0);
  1308.     }
  1309.     (void) getreply(0);
  1310.     code = -1;
  1311.  
  1312.     if (closefunc != NULL && fout != NULL)
  1313.         (*closefunc)(fout);
  1314.  
  1315. #ifdef __SASC
  1316.     SetMode(chkufb(fileno(stdin))->ufbfh,0L);
  1317. #else
  1318.     SetMode(_devtab[fileno(stdin)].fd,0L);
  1319. #endif
  1320.     Enable_Abort = 1;
  1321.  
  1322.     if (bytes > 0)
  1323. #ifdef FTP_LOG_USAGE
  1324.         ptransfer("received", bytes, &start, &stop, remote);
  1325. #else
  1326.     {   ptransfer("received", bytes, &start, &stop);
  1327.         if (log_file) fprintf(log_file,"%s %d\n",hostname, bytes);
  1328.     }
  1329. #endif /* FTP_LOG_USAGE */
  1330. //    (void) signal(SIGINT,oldintr);
  1331. }
  1332.  
  1333. /*
  1334.  * Need to start a listen on the data channel
  1335.  * before we send the command, otherwise the
  1336.  * server's connect may fail.
  1337.  */
  1338. int sendport = -1;
  1339.  
  1340. initconn()
  1341. {
  1342.     register char *p, *a;
  1343.     int result, len, tmpno = 0;
  1344.     int on = 1;
  1345.  
  1346. noport:
  1347.     data_addr = myctladdr;
  1348.     if (sendport)
  1349.         data_addr.sin_port = 0;    /* let system pick one */ 
  1350.     if (data != -1)
  1351.         (void) s_close (data);
  1352.     data = socket(AF_INET, SOCK_STREAM, 0);
  1353.     if (data < 0) {
  1354.         perror("ftp: socket");
  1355.         if (tmpno)
  1356.             sendport = 1;
  1357.         return (1);
  1358.     }
  1359.     if (!sendport)
  1360.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1361.             perror("ftp: setsockopt (reuse address)");
  1362.             goto bad;
  1363.         }
  1364.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1365.         perror("ftp: bind");
  1366.         goto bad;
  1367.     }
  1368.     if (options & SO_DEBUG &&
  1369.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1370.         perror("ftp: setsockopt (ignored)");
  1371.     len = sizeof (data_addr);
  1372.     if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
  1373.         perror("ftp: getsockname");
  1374.         goto bad;
  1375.     }
  1376.     if (listen(data, 1) < 0)
  1377.         perror("ftp: listen");
  1378.     if (sendport) {
  1379.         a = (char *)&data_addr.sin_addr;
  1380.         p = (char *)&data_addr.sin_port;
  1381. #define    UC(b)    (((int)b)&0xff)
  1382.         result =
  1383.             command("PORT %d,%d,%d,%d,%d,%d",
  1384.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1385.               UC(p[0]), UC(p[1]));
  1386.         if (result == ERROR && sendport == -1) {
  1387.             sendport = 0;
  1388.             tmpno = 1;
  1389.             goto noport;
  1390.         }
  1391.         return (result != COMPLETE);
  1392.     }
  1393.     if (tmpno)
  1394.         sendport = 1;
  1395.     return (0);
  1396. bad:
  1397.     (void) s_close(data), data = -1;
  1398.     if (tmpno)
  1399.         sendport = 1;
  1400.     return (1);
  1401. }
  1402.  
  1403. dataconn(mode)
  1404.     char *mode;
  1405. {
  1406.     struct sockaddr_in from;
  1407.     int s, fromlen = sizeof (from);
  1408.  
  1409.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1410.     if (s < 0) {
  1411.         perror("ftp: accept");
  1412.         (void) s_close(data), data = -1;
  1413.         return -1;
  1414.     }
  1415.     (void) s_close(data);
  1416.     data = s;
  1417.     return data;
  1418. }
  1419.  
  1420. #ifdef FTP_LOG_USAGE
  1421. ptransfer(direction, bytes, t0, t1, filename)
  1422. #else
  1423. ptransfer(direction, bytes, t0, t1)
  1424. #endif /* FTP_LOG_USAGE */
  1425.     char *direction;
  1426.     long bytes;
  1427.     struct timeval *t0, *t1;
  1428. #ifdef FTP_LOG_USAGE
  1429.         char *filename;
  1430. #endif /* FTP_LOG_USAGE */
  1431. {
  1432.     struct timeval td;
  1433.     float s, bs;
  1434.  
  1435.     if (verbose) {
  1436.         tvsub(&td, t1, t0);
  1437.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1438. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1439.         bs = bytes / nz(s);
  1440.         printf("%ld bytes %s in %.2f seconds (%.2f Kbytes/s)\n",
  1441.             bytes, direction, s, bs / 1024.);
  1442. #ifdef FTP_LOG_USAGE
  1443.         syslog(LOG_INFO, "%s (%ld bytes) %s\n", filename, bytes, direction);
  1444. #endif /* FTP_LOG_USAGE */
  1445.     }
  1446. }
  1447.  
  1448. /*tvadd(tsum, t0)
  1449.     struct timeval *tsum, *t0;
  1450. {
  1451.  
  1452.     tsum->tv_sec += t0->tv_sec;
  1453.     tsum->tv_usec += t0->tv_usec;
  1454.     if (tsum->tv_usec > 1000000)
  1455.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1456. } */
  1457.  
  1458. tvsub(tdiff, t1, t0)
  1459.     struct timeval *tdiff, *t1, *t0;
  1460. {
  1461.  
  1462.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1463.     if (t1->tv_usec < t0->tv_usec)
  1464.     {    t1->tv_usec += 1000000;
  1465.         tdiff->tv_sec--;
  1466.     }
  1467.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1468. }
  1469.  
  1470. sig_t
  1471. psabort()
  1472. {
  1473.     extern int abrtflag;
  1474.  
  1475.     abrtflag++;
  1476. }
  1477.  
  1478. pswitch(flag)
  1479.     int flag;
  1480. {
  1481. #if 0
  1482.     extern int proxy, abrtflag;
  1483.     sig_t (*oldintr)();
  1484.     static struct comvars {
  1485.         int connect;
  1486.         char name[MAXHOSTNAMELEN];
  1487.         struct sockaddr_in mctl;
  1488.         struct sockaddr_in hctl;
  1489.         FILE *in;
  1490.         FILE *out;
  1491.         int tpe;
  1492.         int cpnd;
  1493.         int sunqe;
  1494.         int runqe;
  1495.         int mcse;
  1496.         int ntflg;
  1497.         char nti[17];
  1498.         char nto[17];
  1499.         int mapflg;
  1500.         char mi[MAXPATHLEN];
  1501.         char mo[MAXPATHLEN];
  1502.         } proxstruct, tmpstruct;
  1503.     struct comvars *ip, *op;
  1504.  
  1505.     abrtflag = 0;
  1506.     oldintr = signal(SIGINT, psabort);
  1507.     if (flag) {
  1508.         if (proxy)
  1509.             return;
  1510.         ip = &tmpstruct;
  1511.         op = &proxstruct;
  1512.         proxy++;
  1513.     }
  1514.     else {
  1515.         if (!proxy)
  1516.             return;
  1517.         ip = &proxstruct;
  1518.         op = &tmpstruct;
  1519.         proxy = 0;
  1520.     }
  1521.     ip->connect = connected;
  1522.     connected = op->connect;
  1523.     if (hostname) {
  1524.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1525.         ip->name[strlen(ip->name)] = '\0';
  1526.     } else
  1527.         ip->name[0] = 0;
  1528.     hostname = op->name;
  1529.     ip->hctl = hisctladdr;
  1530.     hisctladdr = op->hctl;
  1531.     ip->mctl = myctladdr;
  1532.     myctladdr = op->mctl;
  1533. //    ip->in = cin;
  1534. //    cin = op->in;
  1535. //    ip->out = cout;
  1536. //    cout = op->out;
  1537.     ip->tpe = type;
  1538.     type = op->tpe;
  1539.     if (!type)
  1540.         type = 1;
  1541.     ip->cpnd = cpend;
  1542.     cpend = op->cpnd;
  1543.     ip->sunqe = sunique;
  1544.     sunique = op->sunqe;
  1545.     ip->runqe = runique;
  1546.     runique = op->runqe;
  1547.     ip->mcse = mcase;
  1548.     mcase = op->mcse;
  1549.     ip->ntflg = ntflag;
  1550.     ntflag = op->ntflg;
  1551.     (void) strncpy(ip->nti, ntin, 16);
  1552.     (ip->nti)[strlen(ip->nti)] = '\0';
  1553.     (void) strcpy(ntin, op->nti);
  1554.     (void) strncpy(ip->nto, ntout, 16);
  1555.     (ip->nto)[strlen(ip->nto)] = '\0';
  1556.     (void) strcpy(ntout, op->nto);
  1557.     ip->mapflg = mapflag;
  1558.     mapflag = op->mapflg;
  1559.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1560.     (ip->mi)[strlen(ip->mi)] = '\0';
  1561.     (void) strcpy(mapin, op->mi);
  1562.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1563.     (ip->mo)[strlen(ip->mo)] = '\0';
  1564.     (void) strcpy(mapout, op->mo);
  1565.     (void) signal(SIGINT, oldintr);
  1566.     if (abrtflag) {
  1567.         abrtflag = 0;
  1568.         (*oldintr)();
  1569.     }
  1570. #endif
  1571. }
  1572.  
  1573. jmp_buf ptabort;
  1574. int ptabflg;
  1575.  
  1576. sig_t
  1577. abortpt()
  1578. {
  1579.     printf("\n");
  1580.     (void) fflush(stdout);
  1581.     ptabflg++;
  1582.     mflag = 0;
  1583.     abrtflag = 0;
  1584.     longjmp(ptabort, 1);
  1585. }
  1586.  
  1587. proxtrans(cmd, local, remote)
  1588.     char *cmd, *local, *remote;
  1589. {
  1590. #if 0
  1591.     sig_t (*oldintr)(), abortpt();
  1592.     int tmptype, oldtype = 0, secndflag = 0, nfnd;
  1593.     extern jmp_buf ptabort;
  1594.     char *cmd2;
  1595.     struct fd_set mask;
  1596.  
  1597.     if (strcmp(cmd, "RETR"))
  1598.         cmd2 = "RETR";
  1599.     else
  1600.         cmd2 = runique ? "STOU" : "STOR";
  1601.     if (command("PASV") != COMPLETE) {
  1602.         printf("proxy server does not support third part transfers.\n");
  1603.         return;
  1604.     }
  1605.     tmptype = type;
  1606.     pswitch(0);
  1607.     if (!connected) {
  1608.         printf("No primary connection\n");
  1609.         pswitch(1);
  1610.         code = -1;
  1611.         return;
  1612.     }
  1613.     if (type != tmptype) {
  1614.         oldtype = type;
  1615.         switch (tmptype) {
  1616.             case TYPE_A:
  1617.                 setascii();
  1618.                 break;
  1619.             case TYPE_I:
  1620.                 setbinary();
  1621.                 break;
  1622.             case TYPE_E:
  1623.                 setebcdic();
  1624.                 break;
  1625.             case TYPE_L:
  1626.                 settenex();
  1627.                 break;
  1628.         }
  1629.     }
  1630.     if (command("PORT %s", pasv) != COMPLETE) {
  1631.         switch (oldtype) {
  1632.             case 0:
  1633.                 break;
  1634.             case TYPE_A:
  1635.                 setascii();
  1636.                 break;
  1637.             case TYPE_I:
  1638.                 setbinary();
  1639.                 break;
  1640.             case TYPE_E:
  1641.                 setebcdic();
  1642.                 break;
  1643.             case TYPE_L:
  1644.                 settenex();
  1645.                 break;
  1646.         }
  1647.         pswitch(1);
  1648.         return;
  1649.     }
  1650.     if (setjmp(ptabort))
  1651.         goto abort;
  1652.     oldintr = signal(SIGINT, abortpt);
  1653.     if (command("%s %s", cmd, remote) != PRELIM) {
  1654.         (void) signal(SIGINT, oldintr);
  1655.         switch (oldtype) {
  1656.             case 0:
  1657.                 break;
  1658.             case TYPE_A:
  1659.                 setascii();
  1660.                 break;
  1661.             case TYPE_I:
  1662.                 setbinary();
  1663.                 break;
  1664.             case TYPE_E:
  1665.                 setebcdic();
  1666.                 break;
  1667.             case TYPE_L:
  1668.                 settenex();
  1669.                 break;
  1670.         }
  1671.         pswitch(1);
  1672.         return;
  1673.     }
  1674.     Delay(100L);
  1675.     pswitch(1);
  1676.     secndflag++;
  1677.     if (command("%s %s", cmd2, local) != PRELIM)
  1678.         goto abort;
  1679.     ptflag++;
  1680.     (void) getreply(0);
  1681.     pswitch(0);
  1682.     (void) getreply(0);
  1683.     (void) signal(SIGINT, oldintr);
  1684.     switch (oldtype) {
  1685.         case 0:
  1686.             break;
  1687.         case TYPE_A:
  1688.             setascii();
  1689.             break;
  1690.         case TYPE_I:
  1691.             setbinary();
  1692.             break;
  1693.         case TYPE_E:
  1694.             setebcdic();
  1695.             break;
  1696.         case TYPE_L:
  1697.             settenex();
  1698.             break;
  1699.     }
  1700.     pswitch(1);
  1701.     ptflag = 0;
  1702.     printf("local: %s remote: %s\n", local, remote);
  1703.     return;
  1704. abort:
  1705.     (void) signal(SIGINT, SIG_IGN);
  1706.     ptflag = 0;
  1707.     if (strcmp(cmd, "RETR") && !proxy)
  1708.         pswitch(1);
  1709.     else if (!strcmp(cmd, "RETR") && proxy)
  1710.         pswitch(0);
  1711.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1712.         if (command("%s %s", cmd2, local) != PRELIM) {
  1713.             pswitch(0);
  1714.             switch (oldtype) {
  1715.                 case 0:
  1716.                     break;
  1717.                 case TYPE_A:
  1718.                     setascii();
  1719.                     break;
  1720.                 case TYPE_I:
  1721.                     setbinary();
  1722.                     break;
  1723.                 case TYPE_E:
  1724.                     setebcdic();
  1725.                     break;
  1726.                 case TYPE_L:
  1727.                     settenex();
  1728.                     break;
  1729.             }
  1730.             if (cpend) {
  1731.                 char msg[2];
  1732.  
  1733.                 fprintf(cout,"%c%c",IAC,IP);
  1734.                 (void) fflush(cout); 
  1735.                 *msg = IAC;
  1736.                 *(msg+1) = DM;
  1737.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1738.                     perror("abort");
  1739.                 fprintf(cout,"ABOR\r\n");
  1740.                 (void) fflush(cout);
  1741.                 FD_ZERO(&mask);
  1742.                 FD_SET(fileno(cin), &mask);
  1743.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1744.                     if (nfnd < 0) {
  1745.                         perror("abort");
  1746.                     }
  1747.                     if (ptabflg)
  1748.                         code = -1;
  1749.                     lostpeer();
  1750.                 }
  1751.                 (void) getreply(0);
  1752.                 (void) getreply(0);
  1753.             }
  1754.         }
  1755.         pswitch(1);
  1756.         if (ptabflg)
  1757.             code = -1;
  1758.         (void) signal(SIGINT, oldintr);
  1759.         return;
  1760.     }
  1761.     if (cpend) {
  1762.         char msg[2];
  1763.  
  1764.         fprintf(cout,"%c%c",IAC,IP);
  1765.         (void) fflush(cout); 
  1766.         *msg = IAC;
  1767.         *(msg+1) = DM;
  1768.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1769.             perror("abort");
  1770.         fprintf(cout,"ABOR\r\n");
  1771.         (void) fflush(cout);
  1772.         FD_ZERO(&mask);
  1773.         FD_SET(fileno(cin), &mask);
  1774.         if ((nfnd = empty(&mask,10)) <= 0) {
  1775.             if (nfnd < 0) {
  1776.                 perror("abort");
  1777.             }
  1778.             if (ptabflg)
  1779.                 code = -1;
  1780.             lostpeer();
  1781.         }
  1782.         (void) getreply(0);
  1783.         (void) getreply(0);
  1784.     }
  1785.     pswitch(!proxy);
  1786.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1787.         if (command("%s %s", cmd2, local) != PRELIM) {
  1788.             pswitch(0);
  1789.             switch (oldtype) {
  1790.                 case 0:
  1791.                     break;
  1792.                 case TYPE_A:
  1793.                     setascii();
  1794.                     break;
  1795.                 case TYPE_I:
  1796.                     setbinary();
  1797.                     break;
  1798.                 case TYPE_E:
  1799.                     setebcdic();
  1800.                     break;
  1801.                 case TYPE_L:
  1802.                     settenex();
  1803.                     break;
  1804.             }
  1805.             if (cpend) {
  1806.                 char msg[2];
  1807.  
  1808.                 fprintf(cout,"%c%c",IAC,IP);
  1809.                 (void) fflush(cout); 
  1810.                 *msg = IAC;
  1811.                 *(msg+1) = DM;
  1812.                 if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1813.                     perror("abort");
  1814.                 fprintf(cout,"ABOR\r\n");
  1815.                 (void) fflush(cout);
  1816.                 FD_ZERO(&mask);
  1817.                 FD_SET(fileno(cin), &mask);
  1818.                 if ((nfnd = empty(&mask,10)) <= 0) {
  1819.                     if (nfnd < 0) {
  1820.                         perror("abort");
  1821.                     }
  1822.                     if (ptabflg)
  1823.                         code = -1;
  1824.                     lostpeer();
  1825.                 }
  1826.                 (void) getreply(0);
  1827.                 (void) getreply(0);
  1828.             }
  1829.             pswitch(1);
  1830.             if (ptabflg)
  1831.                 code = -1;
  1832.             (void) signal(SIGINT, oldintr);
  1833.             return;
  1834.         }
  1835.     }
  1836.     if (cpend) {
  1837.         char msg[2];
  1838.  
  1839.         fprintf(cout,"%c%c",IAC,IP);
  1840.         (void) fflush(cout); 
  1841.         *msg = IAC;
  1842.         *(msg+1) = DM;
  1843.         if (send(fileno(cout),msg,2,MSG_OOB) != 2)
  1844.             perror("abort");
  1845.         fprintf(cout,"ABOR\r\n");
  1846.         (void) fflush(cout);
  1847.         FD_ZERO(&mask);
  1848.         FD_SET(fileno(cin), &mask);
  1849.         if ((nfnd = empty(&mask,10)) <= 0) {
  1850.             if (nfnd < 0) {
  1851.                 perror("abort");
  1852.             }
  1853.             if (ptabflg)
  1854.                 code = -1;
  1855.             lostpeer();
  1856.         }
  1857.         (void) getreply(0);
  1858.         (void) getreply(0);
  1859.     }
  1860.     pswitch(!proxy);
  1861.     if (cpend) {
  1862.         FD_ZERO(&mask);
  1863.         FD_SET(fileno(cin), &mask);
  1864.         if ((nfnd = empty(&mask,10)) <= 0) {
  1865.             if (nfnd < 0) {
  1866.                 perror("abort");
  1867.             }
  1868.             if (ptabflg)
  1869.                 code = -1;
  1870.             lostpeer();
  1871.         }
  1872.         (void) getreply(0);
  1873.         (void) getreply(0);
  1874.     }
  1875.     if (proxy)
  1876.         pswitch(0);
  1877.     switch (oldtype) {
  1878.         case 0:
  1879.             break;
  1880.         case TYPE_A:
  1881.             setascii();
  1882.             break;
  1883.         case TYPE_I:
  1884.             setbinary();
  1885.             break;
  1886.         case TYPE_E:
  1887.             setebcdic();
  1888.             break;
  1889.         case TYPE_L:
  1890.             settenex();
  1891.             break;
  1892.     }
  1893.     pswitch(1);
  1894.     if (ptabflg)
  1895.         code = -1;
  1896.     (void) signal(SIGINT, oldintr);
  1897. #endif
  1898. }
  1899.  
  1900. reset()
  1901. {
  1902.     struct fd_set mask;
  1903.     int nfnd = 1;
  1904.  
  1905.     FD_ZERO(&mask);
  1906.     while (nfnd > 0) {
  1907.         FD_SET(cin, &mask);
  1908.         if ((nfnd = empty(&mask,0)) < 0) {
  1909.             perror("reset");
  1910.             code = -1;
  1911.             lostpeer();
  1912.         }
  1913.         else if (nfnd) {
  1914.             (void) getreply(0);
  1915.         }
  1916.     }
  1917. }
  1918.  
  1919. char *
  1920. gunique(local)
  1921.     char *local;
  1922. {
  1923.     static char new[MAXPATHLEN];
  1924.     char *cp = rindex(local, '/');
  1925.     int d, count=0;
  1926.     char ext = '1';
  1927.  
  1928.     if (cp)
  1929.         *cp = '\0';
  1930.     d = access(cp ? local : ".", 2);
  1931.     if (cp)
  1932.         *cp = '/';
  1933.     if (d < 0) {
  1934.         perror(local);
  1935.         return((char *) 0);
  1936.     }
  1937.     (void) strcpy(new, local);
  1938.     cp = new + strlen(new);
  1939.     *cp++ = '.';
  1940.     while (!d) {
  1941.         if (++count == 100) {
  1942.             printf("runique: can't find unique file name.\n");
  1943.             return((char *) 0);
  1944.         }
  1945.         *cp++ = ext;
  1946.         *cp = '\0';
  1947.         if (ext == '9')
  1948.             ext = '0';
  1949.         else
  1950.             ext++;
  1951.         if ((d = access(new, 0)) < 0)
  1952.             break;
  1953.         if (ext != '0')
  1954.             cp--;
  1955.         else if (*(cp - 2) == '.')
  1956.             *(cp - 1) = '1';
  1957.         else {
  1958.             *(cp - 2) = *(cp - 2) + 1;
  1959.             cp--;
  1960.         }
  1961.     }
  1962.     return(new);
  1963. }
  1964.